#include <stdio.h>
#include <windows.h>
#include "exp_api.h"

#include "jpeg-6b/jpeglib.h"
#pragma comment(lib, "jpeg-6b/Release/jpeg.lib")

#include <setjmp.h>

#include "exjpeg.h"

extern jpeg_opt exp_opt;

//---------------------------------------------------------------------------
int __stdcall GetPluginInfo (int infono, char *buf, int buflen)
{
    char *infomation[] = {
      /* 0 */  "T0XN",
      /* 1 */  "JPEG export library v0.0.3.0 by 43T",
      /* 2 */  "JPEG",
      /* 3 */  ".jpg",
      /* X */  ".jpeg", //この仕様は失敗？
    };
    if (infono < 0 || infono >= 4) 
        return 0;

	if (exp_opt.extjpeg) infomation[3] = infomation[4];
    lstrcpyn(buf, infomation[infono], buflen);

    return lstrlen(buf);
}
//---------------------------------------------------------------------------
int __stdcall IsSupported (int colorDepth)
{
    /* 色深度を確認 */
    if (colorDepth == 24)
        return 1;

    return 0;
}
//---------------------------------------------------------------------------
int write_JPEG_file (char *filepath, BITMAPINFOHEADER *bmih, char *pbmdat,
			PictureInfo *lpInfo, struct jpeg_opt *pexp_opt,
    int (CALLBACK *lpPrgressCallback)(int,int,long),
                long lData)
{
    int ret = XPI_ALL_RIGHT;

    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE *outfile;		/* target file */
    JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
    int row_stride;		/* physical row width in image buffer */

    JSAMPLE *image_buffer;	/* Points to large array of R,G,B-order data */
    JSAMPLE *adr;	/* Points to large array of R,G,B-order data */
    int image_height;	/* Number of rows in image */
    int image_width;	/* Number of columns in image */

    int rrr, /*ggg,*/ bbb, xx;
    //int ny;
	char *comment_text; //コメント

    /* Initialize the JPEG compression object with default error handling. */
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);

    if ((outfile = fopen(filepath, "wb")) == NULL) {
        //fprintf(stderr, "can't open\n");
        jpeg_destroy_compress(&cinfo);
        return XPI_FILE_WRITE_ERROR;
    }
    jpeg_stdio_dest(&cinfo, outfile);

    image_height = bmih->biHeight;
    image_width  = bmih->biWidth;
    image_buffer = (JSAMPLE *)pbmdat;

    cinfo.image_width = image_width; 	/* image width and height, in pixels */
    cinfo.image_height = image_height;
    cinfo.input_components = 3;		/* # of color components per pixel */
    cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, pexp_opt->qual, TRUE /* limit to baseline-JPEG values */);
    if (pexp_opt->prog)
        jpeg_simple_progression(&cinfo);

    jpeg_start_compress(&cinfo, TRUE);
	//コメントを書きこむ
    if (pexp_opt->comment && lpInfo->hInfo != NULL) {
        comment_text = (char *)LocalLock(lpInfo->hInfo);
        jpeg_write_marker(&cinfo, JPEG_COM, comment_text, strlen(comment_text));
        LocalUnlock(lpInfo->hInfo);
    }

    //if (lpPrgressCallback != NULL) lpPrgressCallback(0,0,0);
    row_stride = (image_width * 3 + 3) & (~3); /* JSAMPLEs per row in image_buffer */
    //ny=0;
    while (cinfo.next_scanline < cinfo.image_height) {
        //if (lpPrgressCallback != NULL) lpPrgressCallback(ny+1, image_height+1, lData);
        adr = row_pointer[0] =
                &image_buffer[(image_height - cinfo.next_scanline -1) * row_stride];
        for (xx=0; xx < image_width; xx++) {
    	    bbb = adr[0];
            //ggg = adr[1];
            rrr = adr[2];
            adr[0] = rrr;
            //adr[1] = ggg;
            adr[2] = bbb;
            adr+=3;
        }
        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
        //ny++;
    }

    jpeg_finish_compress(&cinfo);
    fclose(outfile);
    jpeg_destroy_compress(&cinfo);

    //if (lpPrgressCallback != NULL) lpPrgressCallback(image_height+1, image_height+1, lData);

    return ret;
}
//---------------------------------------------------------------------------
int __stdcall CreatePicture (
                char *filepath, unsigned int flag,
                HANDLE *pHBInfo, HANDLE *pHBm, PictureInfo *lpInfo,
    int (CALLBACK *lpPrgressCallback)(int,int,long),
                long lData)
{
    int ret;
	BITMAPINFOHEADER *bmih;
	char *pbmdat;

    if (exp_opt.qual < 1)   exp_opt.qual = 1;
    if (exp_opt.qual > 100) exp_opt.qual = 100;

    /* flag check */
	switch (flag) {
		case 0: //メモリハンドル
		    bmih = (BITMAPINFOHEADER*)LocalLock(*pHBInfo);
			pbmdat = (char *)LocalLock(*pHBm);
			break;
		case 1: //メモリのアドレス
		    bmih = (BITMAPINFOHEADER*)pHBInfo;
			pbmdat = (char *)pHBm;
			break;
		default:
    	return XPI_NO_FUNCTION;
	}

    ret = write_JPEG_file(filepath, bmih, pbmdat, lpInfo, &exp_opt, lpPrgressCallback, lData);

	switch (flag) {
		case 0: //メモリハンドル
		    LocalUnlock(*pHBInfo);
			LocalUnlock(*pHBm);
			break;
		case 1: //メモリのアドレス
			break;
	}

    return ret;
}
//---------------------------------------------------------------------------
